
package controller;

import java.io.File;
import java.io.IOException;

import model.ClientModel;
import model.ServerOnClientModel;
import utils.Command;
import utils.ConsoleTextEditor;
import utils.Constants;
import view.ClientView;

public class ClientController {
    
    // Index for received answer command and message
    private static final int COMMAND = 0;
    private static final int MESSAGE = 1;
    
    // Index for user imput on option and extra
    private static final int OPTION = 0;
    private static final int EXTRA = 1;
    
    private ClientModel clientModel;
    private ClientView clientView;
    private ServerOnClientModel serverOnClientModel;
    
    public ClientController(ClientModel clientModel, ClientView clientView) {
        this.clientModel = clientModel;
        this.clientView = clientView;
        serverOnClientModel = new ServerOnClientModel(clientModel.getPort());
    }
    
    public void start() {
        
        String[] received;
        String[] optionChosen;
        
        if (clientModel.connect()) {
            received = clientModel.receiveAnswerTo(Command.CLIENT_NAME,
                    clientModel.getMyIp());
            
            serverOnClientModel.startConnection();
            
            AcceptingThread acceptingThread = new AcceptingThread();
            acceptingThread.start();
            
            while (!received[COMMAND].equals(Command.SOCKET_FAIL)) {
                optionChosen = clientView.getUserChoice();
                
                switch (optionChosen[OPTION]) {
                    case ClientView.OPTION_CREATE_FILE:
                        received = optionCreateFile(optionChosen[EXTRA]);
                        break;
                    case ClientView.OPTION_READ_FILE:
                        received = optionReadFile(optionChosen[EXTRA]);
                        break;
                    case ClientView.OPTION_DELETE_FILE:
                        received = optionDeleteFile(optionChosen[EXTRA]);
                        break;
                    case ClientView.OPTION_MOVE_FILE:
                        received = optionDownloadFile(optionChosen[EXTRA]);
                        break;
                    case ClientView.OPTION_EDIT_FILE:
                        received = optionEditFile(optionChosen[EXTRA]);
                        break;
                    case ClientView.OPTION_EXIT:
                        received = optionExit();
                        break;
                    default:
                        break;
                }
            }
            
            clientModel.closeConnection();
        } else {
            clientView.showMessage(Constants.ERROR_SERVER_DOWN);
        }
    }
    
    private String[] optionCreateFile(String fileName) {
        
        String[] receivedTotal;
        long timeInit, timeEnd = 0, timeTotal;
        timeInit = System.currentTimeMillis();
        receivedTotal = clientModel.receiveAnswerTo(Command.CREATE_FILE,
                fileName);
        if (receivedTotal[COMMAND].equals(Command.OK)) {
            if (clientModel.createFile(fileName)) {
                timeEnd = System.currentTimeMillis();
                clientView.showMessage("Arquivo criado com sucesso!");
                ConsoleTextEditor.edit(fileName);
                receivedTotal = clientModel.receiveAnswerTo(
                        Command.FINISH_USING, fileName);
            } else {
                receivedTotal = clientModel.receiveAnswerTo(Command.DB_REMOVE,
                        fileName);
                clientView.showMessage("Erro! Falha ao criar o arquivo!");
            }
        } else {
            if (receivedTotal[COMMAND].equals(Command.ERROR)) {
                clientView.showMessage("Erro! Arquivo já existente!");
            }
        }
        timeTotal = timeEnd - timeInit;
        try {
            clientModel.printTime(Constants.TIME_CREATE, timeTotal);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return receivedTotal;
    }
    
    private String[] optionReadFile(String fileName) {
        
        String[] receivedTotal;
        
        long timeInit, timeEnd, timeTotal;
        timeInit = System.currentTimeMillis();
        receivedTotal = clientModel.receiveAnswerTo(Command.READ_FILE,
                fileName);
        if (receivedTotal[COMMAND].equals(Command.OK)) {
            if (receivedTotal[EXTRA].equalsIgnoreCase("local")) {
                clientView.printFile(fileName);
                receivedTotal = clientModel.receiveAnswerTo(
                        Command.FINISH_USING, fileName);
            } else {
                try {
                    clientModel.receiveFile(receivedTotal[EXTRA], fileName);
                    clientView.printFile(fileName);
                    clientModel.deleteFile(fileName);
                    receivedTotal = clientModel.receiveAnswerTo(
                            Command.FINISH_USING, fileName);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        } else {
            if (receivedTotal[COMMAND].equals(Command.ERROR)) {
                clientView.showMessage("Erro! Arquivo não existente!");
            } else {
                if (receivedTotal[COMMAND].equals(Command.UNAVAILABLE_FILE)) {
                    clientView.showMessage("Erro! Arquivo não disponível!");
                } else {
                    if (receivedTotal[COMMAND].equals(Command.UNAVAILABLE_OP)) {
                        clientView
                                .showMessage("Erro! Operação não disponível no momento!");
                    }
                }
            }
        }
        timeEnd = System.currentTimeMillis();
        timeTotal = timeEnd - timeInit;
        try {
            clientModel.printTime(Constants.TIME_READ, timeTotal);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return receivedTotal;
    }
    
    private String[] optionDeleteFile(String fileName) {
        
        String[] receivedTotal;
        
        long timeInit, timeEnd, timeTotal;
        timeInit = System.currentTimeMillis();
        receivedTotal = clientModel.receiveAnswerTo(Command.DELETE_FILE,
                fileName);
        if (receivedTotal[COMMAND].equals(Command.OK)) {
            clientModel.deleteFile(fileName);
            clientView.showMessage("Arquivo deletado com sucesso!");
        } else {
            clientView.showMessage("Erro!");
        }
        
        timeEnd = System.currentTimeMillis();
        timeTotal = timeEnd - timeInit;
        try {
            clientModel.printTime(Constants.TIME_DELETE, timeTotal);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return receivedTotal;
    }
    
    private String[] optionDownloadFile(String fileName) {
        
        String[] receivedTotal;
        
        long timeInit, timeEnd, timeTotal;
        timeInit = System.currentTimeMillis();
        File file = new File(fileName);
        if (file.exists()) {
            System.out.println("Arquivo já existe localmente!");
            receivedTotal = new String[] {
                    Command.OK
            };
        } else {
            receivedTotal = clientModel.receiveAnswerTo(Command.READ_FILE,
                    fileName);
            if (receivedTotal[COMMAND].equals(Command.OK)) {
                try {
                    clientModel.receiveFile(receivedTotal[EXTRA], fileName);
                    receivedTotal = clientModel.receiveAnswerTo(Command.DB_ADD,
                            fileName);
                    receivedTotal = clientModel.receiveAnswerTo(
                            Command.FINISH_USING,
                            fileName);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } else {
                if (receivedTotal[COMMAND].equals(Command.ERROR)) {
                    clientView.showMessage("Erro! Arquivo não existente!");
                } else {
                    if (receivedTotal[COMMAND].equals(Command.UNAVAILABLE_FILE)) {
                        clientView.showMessage("Erro! Arquivo não disponível!");
                    } else {
                        if (receivedTotal[COMMAND]
                                .equals(Command.UNAVAILABLE_OP)) {
                            clientView
                                    .showMessage("Erro! Operação não disponível no momento!");
                        }
                    }
                }
            }
        }
        
        timeEnd = System.currentTimeMillis();
        timeTotal = timeEnd - timeInit;
        try {
            clientModel.printTime(Constants.TIME_DOWNLOAD, timeTotal);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return receivedTotal;
    }
    
    private String[] optionEditFile(String fileName) {
        
        String[] receivedTotal;
        
        receivedTotal = clientModel.receiveAnswerTo(Command.EDIT_FILE,
                fileName);
        if (receivedTotal[COMMAND].equals(Command.OK)) {
            ConsoleTextEditor.edit(fileName);
            try {
                clientModel.sendFile(receivedTotal[EXTRA], fileName);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            receivedTotal = clientModel.receiveAnswerTo(
                    Command.FINISH_USING, fileName);
        } else {
            if (receivedTotal[COMMAND].equals(Command.ERROR)) {
                clientView.showMessage("Erro!");
            }
        }
        
        return receivedTotal;
    }
    
    private String[] optionExit() {
        return new String[] {
                Command.SOCKET_FAIL
        };
        
    }
    
    private class AcceptingThread extends Thread {
        
        @Override
        public void run() {
            while (!isInterrupted()) {
                serverOnClientModel.acceptNewClient();
            }
        }
    }
    
}
